import SelectWidget from '@rjsf/antd/lib/widgets/SelectWidget';
import {
  FormContextType,
  RJSFSchema,
  StrictRJSFSchema,
  WidgetProps,
} from '@rjsf/utils';
import { useContext } from 'react';
import {
  PickInputValueType,
  getMultiPickResultUUID,
  BasePickInputProps,
} from '../../pick-input/3d';
import { PickInputRJSFFormat, selectionIDPrefix } from '../constants';
import { PickableFormContext } from '../pickable-provider';
import { PickInputForFocus } from '../auto-focus/pick-input';
import { decodeComposedFormat } from '../utils';

export const CustomSelectWidget = function <
  T = any,
  S extends StrictRJSFSchema = RJSFSchema,
  F extends FormContextType = any,
>(props: WidgetProps<T, S, F>) {
  const selectionMap = useContext(PickableFormContext);

  const uiOptions = props.uiSchema?.['ui:options'];

  const showArrow = uiOptions?.showArrow as boolean;
  const curveReversable = uiOptions?.curveReversable as boolean;

  const focusID = uiOptions?.focusID as number;
  const canBeAutoFocused = uiOptions?.canBeAutoFocused as boolean;
  const autoFocus = props.uiSchema?.['ui:autofocus'];
  const nameRenderer =
    uiOptions?.nameRenderer as BasePickInputProps['nameRenderer'];
  const disallowedPickType =
    uiOptions?.disallowedPickType as BasePickInputProps['disallowedPickType'];
  const highlightSelection =
    uiOptions?.highlightSelection as BasePickInputProps['highlightSelection'];
  const allowPickInvisibleAssembleFromLeftPanel =
    uiOptions?.allowPickInvisibleAssembleFromLeftPanel as boolean;

  const allowInfiniteLine = uiOptions?.allowInfiniteLine as boolean;
  const allowInfinitePlane = uiOptions?.allowInfinitePlane as boolean;

  const allowTypeMap = {
    [PickInputRJSFFormat.MultiPickModel]: PickInputValueType.Model,
    [PickInputRJSFFormat.MultiPickCurve]: PickInputValueType.Curve,
    [PickInputRJSFFormat.MultiPickSketch]: PickInputValueType.Sketch,
    [PickInputRJSFFormat.MultiPickFace]: PickInputValueType.Surface,
    [PickInputRJSFFormat.MultiPickPlane]: PickInputValueType.Plane,
    [PickInputRJSFFormat.MultiPickVertex]: PickInputValueType.Vertex,
    [PickInputRJSFFormat.MultiPickALL]: PickInputValueType.ALL,
    [PickInputRJSFFormat.MultiPickProduct]: PickInputValueType.Product,
    [PickInputRJSFFormat.MultiPickPartArray]: PickInputValueType.PartArray,
  };
  const validFormats: string[] = Object.keys(allowTypeMap);

  const formats = decodeComposedFormat(props.schema.format).filter((v) =>
    validFormats.includes(v),
  );

  const pickFilter =
    uiOptions?.pickFilter as any as BasePickInputProps['pickFilter'];

  if (formats.length > 0) {
    const allowType = Array.from(new Set(formats.map((v) => allowTypeMap[v])));

    return (
      <PickInputForFocus
        focusID={focusID}
        pickFilter={pickFilter}
        autoFocus={autoFocus}
        canBeAutoFocused={canBeAutoFocused ?? true}
        allowInfiniteLine={allowInfiniteLine}
        allowInfinitePlane={allowInfinitePlane}
        showArrow={showArrow}
        curveReversable={curveReversable}
        allowPickType={allowType}
        value={props.value.map((v) => selectionMap.get(v))}
        disabled={props.disabled}
        onPick={(pickResult) => {
          // rjsf会将一个选取实例递归后再生成，其中的getter等函数都会丢失
          const result: string[] = [];
          pickResult.forEach((r) => {
            const uuid = getMultiPickResultUUID(r);
            const key = `${selectionIDPrefix}${uuid}`;

            selectionMap.set(key, r);

            result.push(key);
          });

          props.onChange(result);
        }}
        nameRenderer={nameRenderer}
        disallowedPickType={disallowedPickType}
        allowPickInvisibleAssembleFromLeftPanel={
          allowPickInvisibleAssembleFromLeftPanel
        }
        isMulti
        controlled
        placeholder={props.placeholder ?? props.uiSchema['ui:placeholder']}
        highlightSelection={highlightSelection}
      />
    );
  }

  return <SelectWidget {...props} />;
};
